package org.aeon.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.aeon.config.Config;
import org.aeon.protocol.MessageCodecSharable;
import org.aeon.protocol.ProtocolFrameDecoder;
import org.aeon.server.handler.Inbound.FriendApplyListRequestHandler;
import org.aeon.server.handler.HeartbeatDetectionHandler;
import org.aeon.server.handler.Inbound.*;
import org.aeon.server.handler.outbound.ResponseMessageHandler;

/**
 * @author: MissingAeon
 * @date: 2024/1/25 11:48
 * @description: 服务器实现
 */
@Slf4j
public class ChatServer {
    private final ServerBootstrap serverBootstrap;
    // 事件循环组
    private final NioEventLoopGroup CONNECT;
    private final NioEventLoopGroup WORK;
    // 日志
    private final LoggingHandler LOGGING_HANDLER;
    // 消息编码解码器
    private final MessageCodecSharable MESSAGE_CODEC;
    // 退出处理
    private final ChannelConnectHandler CHANNEL_HANDLER;


    public ChatServer() {
        log.debug("正在初始化...");
        CONNECT = new NioEventLoopGroup();
        WORK = new NioEventLoopGroup();
        LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
        MESSAGE_CODEC = new MessageCodecSharable();
        CHANNEL_HANDLER = new ChannelConnectHandler();
        serverBootstrap = new ServerBootstrap();
        init();
    }

    private void init() {
        // 业务处理器
        final LoginRequestHandler LOGIN_HANDLER = new LoginRequestHandler();
        final ResponseMessageHandler RESPONSE_HANDLER = new ResponseMessageHandler();
        final ChatRequestHandler CHAT_HANDLER = new ChatRequestHandler();
        final RegisterRequestHandler REGISTRATION_HANDLER = new RegisterRequestHandler();
        final RequestHandler REQUEST_HANDLER = new RequestHandler();
        final CancelLoginRequestHandler CANCEL_LOGIN_HANDLER = new CancelLoginRequestHandler();
        final FriendApplyRequestHandler FRIEND_APPLY_HANDLER = new FriendApplyRequestHandler();
        final FriendApplyListRequestHandler FRIEND_APPLY_LIST_HANDLER = new FriendApplyListRequestHandler();
        final FriendAddRequestHandler ADD_FRIENDS_HANDLER = new FriendAddRequestHandler();
        final HeartbeatDetectionHandler HEARTBEAT_DETECTION = new HeartbeatDetectionHandler();
        final FriendDeleteRequestHandler DELETE_FRIENDS_HANDLER = new FriendDeleteRequestHandler();
        final ListQueryRequestHandler LIST_QUERY_HANDLER = new ListQueryRequestHandler();
        final GroupChatRequestHandler GROUP_CHAT_HANDLER = new GroupChatRequestHandler();
        final GroupsListRequestHandler GROUPS_LIST_HANDLER = new GroupsListRequestHandler();
        final BlacklistModifyRequestHandler BLACK_MODIFY_HANDLER = new BlacklistModifyRequestHandler();
        final GroupCreateRequestHandler GROUP_CREATE_HANDLER = new GroupCreateRequestHandler();
        final GroupMembersRequestHandler GROUP_MEMBERS_HANDLER = new GroupMembersRequestHandler();
        final GroupJoinRequestHandler GROUP_JOIN_HANDLER = new GroupJoinRequestHandler();
        final GroupQuitRequestHandler GROUP_QUIT_HANDLER = new GroupQuitRequestHandler();
        final SearchRequestHandler SEARCH_HANDLER = new SearchRequestHandler();
        final UserInfoRequestHandler USER_INFO_HANDLER = new UserInfoRequestHandler();
        final GroupInfoRequestHandler GROUP_INFO_HANDLER = new GroupInfoRequestHandler();
        log.debug("正在启动服务器...");
        try {
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.group(CONNECT, WORK);
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new ProtocolFrameDecoder());
                    // ch.pipeline().addLast(LOGGING_HANDLER);
                    ch.pipeline().addLast(MESSAGE_CODEC);
                    ch.pipeline().addLast(RESPONSE_HANDLER);
                    // 心跳检测
                    ch.pipeline().addLast(new IdleStateHandler(10, 0, 0));
                    ch.pipeline().addLast(HEARTBEAT_DETECTION);
                    // 账号
                    ch.pipeline().addLast(REQUEST_HANDLER);
                    ch.pipeline().addLast(CANCEL_LOGIN_HANDLER);
                    ch.pipeline().addLast(REGISTRATION_HANDLER);
                    ch.pipeline().addLast(LOGIN_HANDLER);
                    // 关系
                    ch.pipeline().addLast(FRIEND_APPLY_HANDLER);
                    ch.pipeline().addLast(ADD_FRIENDS_HANDLER);
                    ch.pipeline().addLast(DELETE_FRIENDS_HANDLER);
                    ch.pipeline().addLast(BLACK_MODIFY_HANDLER);
                    ch.pipeline().addLast(LIST_QUERY_HANDLER);
                    ch.pipeline().addLast(FRIEND_APPLY_LIST_HANDLER);
                    // 群组
                    ch.pipeline().addLast(GROUP_CREATE_HANDLER);
                    ch.pipeline().addLast(GROUP_MEMBERS_HANDLER);
                    ch.pipeline().addLast(GROUP_JOIN_HANDLER);
                    ch.pipeline().addLast(GROUP_QUIT_HANDLER);
                    ch.pipeline().addLast(GROUPS_LIST_HANDLER);
                    // 聊天
                    ch.pipeline().addLast(GROUP_CHAT_HANDLER);
                    ch.pipeline().addLast(CHAT_HANDLER);
                    // 搜索
                    ch.pipeline().addLast(SEARCH_HANDLER);
                    ch.pipeline().addLast(USER_INFO_HANDLER);
                    ch.pipeline().addLast(GROUP_INFO_HANDLER);
                    // 断开
                    ch.pipeline().addLast(CHANNEL_HANDLER);
                }
            });
        } catch (Exception e) {
            CONNECT.shutdownGracefully();
            WORK.shutdownGracefully();
            log.error("服务器出错...", e);
        }
    }

    public void startUp() {
        try {
            final Channel channel = serverBootstrap.bind(Config.getServerPort()).sync().channel();
            log.debug("服务器启动完成...");
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("服务器出错...", e);
        } finally {
            CONNECT.shutdownGracefully();
            WORK.shutdownGracefully();
            log.debug("服务器关闭完成...");
        }
    }
}
